package com.gitee.wsl.compose.chart.sample

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.absolutePadding
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
//import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.gitee.wsl.compose.chart.ChartLayout
import com.gitee.wsl.compose.chart.ExperimentalKoalaPlotApi
import com.gitee.wsl.compose.chart.generateHueColorPalette
import com.gitee.wsl.compose.chart.xy.XYGraph
import com.gitee.wsl.compose.chart.xy.axis.model.FloatLinearAxisModel
import com.gitee.wsl.compose.chart.xy.axis.style.TickPosition
import com.gitee.wsl.compose.chart.xy.axis.style.rememberAxisStyle
import com.gitee.wsl.compose.chart.xy.bar.DefaultBar

import com.gitee.wsl.compose.chart.xy.bar.model.BarEntry
import com.gitee.wsl.compose.chart.xy.bar.model.BarPosition
import com.gitee.wsl.compose.chart.xy.bar.VerticalBarPlot
import com.gitee.wsl.compose.modifier.input.gestures.GestureConfig
import com.gitee.wsl.compose.modifier.layout
import com.gitee.wsl.compose.modifier.layout.VerticalRotation
import com.gitee.wsl.compose.modifier.layout.rotateVertically
import com.gitee.wsl.ext.number.toString


private val colors = generateHueColorPalette(fibonacci.size)
private const val BarWidth = 0.8f

private fun barChartEntries(): List<BarEntry<Float, Float>> {
    return buildList {
        fibonacci.forEachIndexed { index, fl ->
            add(BarEntry((index + 1).toFloat(), BarPosition(0f, fl)))
        }
    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
val verticalBarSampleView = object : SampleView {
    override val name: String = "Vertical Bar"

    override val thumbnail = @Composable {
        ThumbnailTheme {
            BarSamplePlot(true, TickPositionState(TickPosition.None, TickPosition.None), name)
        }
    }

    override val content: @Composable () -> Unit = @Composable {
        var tickPositionState by remember {
            mutableStateOf(
                TickPositionState(
                    TickPosition.Outside,
                    TickPosition.Outside
                )
            )
        }

        Column {
            ChartLayout(
                modifier = Modifier.sizeIn(minHeight = 200.dp, maxHeight = 600.dp).weight(1f)
            ) {
                BarSamplePlot(false, tickPositionState, "Fibonacci Sequence")
            }
            //HorizontalDivider(modifier = Modifier.fillMaxWidth())
            TickPositionSelector(tickPositionState) {
                tickPositionState = it
            }
        }
    }
}

private val YAxisRange = 0f..25f
private val XAxisRange = 0.5f..8.5f

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
private fun BarSamplePlot(
    thumbnail: Boolean = false,
    tickPositionState: TickPositionState,
    title: String
) {
    val barChartEntries = remember(thumbnail) { barChartEntries() }

    ChartLayout(
        modifier = paddingMod,
        title = { ChartTitle(title) }
    ) {
        XYGraph(
            xAxisModel = FloatLinearAxisModel(
                XAxisRange,
                minimumMajorTickIncrement = 1f,
                minimumMajorTickSpacing = 10.dp,
                //zoomRangeLimit = 3f,
                minorTickCount = 0
            ),
            yAxisModel = FloatLinearAxisModel(
                YAxisRange,
                minimumMajorTickIncrement = 1f,
                minorTickCount = 0
            ),
            xAxisStyle = rememberAxisStyle(
                tickPosition = tickPositionState.horizontalAxis,
                color = Color.LightGray
            ),
            xAxisLabels = {
                if (!thumbnail) {
                    AxisLabel(it.toString(0), Modifier.padding(top = 2.dp))
                }
            },
            xAxisTitle = { if (!thumbnail) AxisTitle("Position in Sequence") },
            yAxisStyle = rememberAxisStyle(tickPosition = tickPositionState.verticalAxis),
            yAxisLabels = {
                if (!thumbnail) AxisLabel(it.toString(1), Modifier.absolutePadding(right = 2.dp))
            },
            yAxisTitle = {
                if (!thumbnail) {
                    AxisTitle(
                        "Value",
                        modifier = Modifier.layout {
                               rotateVertically(VerticalRotation.COUNTER_CLOCKWISE)
                            }
                            .padding(bottom = padding)
                    )
                }
            },
            gestureConfig = GestureConfig.ABLE_PAN_ZOOM_XY,
            verticalMajorGridLineStyle = null
        ) {
            VerticalBarPlot(
                barChartEntries,
                bar = { index ->
                    DefaultBar(
                        brush = SolidColor(colors[0]),
                        modifier = Modifier.fillMaxWidth(),
                    ) {
                        if (!thumbnail) {
                            HoverSurface { Text(barChartEntries[index].y.yMax.toString()) }
                        }
                    }
                },
                barWidth = BarWidth
            )
        }
    }
}

private data class TickPositionState(
    val verticalAxis: TickPosition,
    val horizontalAxis: TickPosition
)

@Composable
private fun TickPositionSelector(
    state: TickPositionState,
    update: (TickPositionState) -> Unit
) {
    ExpandableCard(
        modifier = paddingMod,
        titleContent = { Text("Axis options", modifier = paddingMod) }
    ) {
        Row {
            Column {
                Text("Vertical")
                TickPosition.entries.forEach {
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        RadioButton(
                            it == state.verticalAxis,
                            onClick = { update(state.copy(verticalAxis = it)) }
                        )
                        Text(it.name)
                    }
                }
            }
            Column {
                Text("Horizontal")
                TickPosition.entries.forEach {
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        RadioButton(
                            it == state.horizontalAxis,
                            onClick = { update(state.copy(horizontalAxis = it)) }
                        )
                        Text(it.name)
                    }
                }
            }
        }
    }
}
